home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 1993-01-21 | 59.2 KB | 1,570 lines
//***************************************************************************** // C_View.prg // View class for OBJECT v2.03 // Copyright (c) 1991, JHK, JHK-Software, Piestany // Please compile with: /N/M/W/A //----------------------------------------------------------------------------- #include "InKey.ch" #include "Object.ch" #include "SetCurs.ch" #define v_data_sep "∞" //data separator in field->Data (database cIFR) always must be one char. #define n_foot_max 250 //length of Top and Bottom string of Report #define v_fnc_info "N:Abs(n) C:AllTrim(c) N:Asc(n) N:At(c,c) C:CdoW(d) C:Chr(c) "+; "C:CMonth(d) D:CtoD(c) D:Date() N:Day(d) X:Descend(e) N:DoW(d) "+; "C:DtoC(d) C:DtoS(d) L:Empty(e) N:Exp(n) C:GetEnv(c) X:If(l,e1,e2) "+; "L:IsAlpha(c) L:IsDigit(c) L:IsLower(c) L:IsUpper(c) C:Left(c,n) N:Log(n) "+; "C:Lower(c) C:LTrim(c) X:Max(nd,nd) X:Min(nd,nd) N:Month(d) C:Pad_(e,n,c) "+; "C:Right(c,n) N:Round(n,n) C:RTrim(c) N:Sqrt(n) C:Str(n,n,n) C:StrTran(...) "+; "C:SubStr(c,n,n) C:Trans(e,c) C:Type(e) C:Upper(c) N:Val(c) C:ValType(e) "+; "N:Year(d)" static VList:={} //list of currently active view objects, add/delete: View(),Edit() / Done() static nViewID:=0 //WORK:ViewID counter, see View`Init(), used for locate in cIFR static nIndex:=0 //WORK:index into View`Report, used in programmer's defining report create class View from DBrowse export: var ViewID //0 //this is unique # for each primary View object.(thread tasks are the same ViewID), used for locate in cIFR. var MenuID //0 //for SlipMenu, used in View/Edit process var MenuNtxID //0 //for Menu`DisableItem() (thread tasks) var MenuFltID //0 //for Menu`DisableItem() (thread tasks) var MenuRptID //0 //for Menu`DisableItem() (thread tasks) var CanGoto //true //enable/disable Goto command for current view var Fields //{} //saved; structure: {{cLongName,cShortName,cAlias,cField,cPicture,bWhen,bValid[,nMemoRowSize,nMemoColSize[,bDoGet]]},...} var Action //{} //saved; structure: {{nKey,bNewProc,bPreviousProc,cShortInfo},...} var Filter //{{},{},{},{}} //saved; structure: {{cName,...},{cExpr,...},{lCanModify,...},{lMarkColor,...} var Report //{{},{},{}} //saved; structure: {{cName,...},{{cTop,aFields,cBottom,lOnlyTotals},...},{lCanModify,...}} //aFields:={cShortName,cTitle,cField,cPicture,lTotal,cSubTotal} method New=ViewNew //o:New() --> self method Copy=ViewCopy //o:Copy() --> copy_of_current_view_object method CreateObj=ViewCreateObj //o:CreateObj() --> new object of this class method Init=ViewInit //o:Init() method Select=ViewSelect //o:Select(cAlias) method DefWindow=ViewDefWindow //o:DefWindow(Name,R,C,Rs,Cs,Clr) method AddBlock=ViewAddBlock //o:AddBlock(cLongName,cShortName,cVarName,bBlock,bDoGet,cPicture,bWhen,bValid) method AddMemo=ViewAddMemo //o:AddMemo(cLongName,cShortName,cField,bWhen,bValid,nRowSize,nColSize) method AddField=ViewAddField //o:AddField(cLongName,cShortName,cField,cPicture,bWhen,bValid) method AddFilter=ViewAddFilter //o:AddFilter(cName,cExpr,lMark) method AddRAll=ViewAddRAll //o:AddRAll(cName,cTop,aFields,cBottom,lOnlyTotals) //add all report: cName=menu_name,{"top_line1;line2",{{ShortName,cField,lTotal,cSubTotal},{ShortName...},...},"bottom_line1;line2",false} method AddReport=ViewAddReport //o:AddReport(cName,lOnlyTotals) //one: "menu_name" method AddRTop=ViewAddRTop //o:AddRTop(cTop) //one: "top_line_1;top_line2..." method AddRField=ViewAddRField //o:AddRField(cTitle,aField,cPicture,lTotal,cSubTotal) //repeat:"ShortName,cField,lTotal,cSubTotal;ShortName..." method AddRBottom=ViewAddRBottom //o:AddRBottom(cBottom) //one: "bottom_line1;line2..."} method AddAction=ViewAddAction //o:AddAction(nKey,bProcedure,cInfo) method View=ViewView //o:View(ID,Name,R,C,Rs,Cs,Clr,Shadow) //ID is menu id number (this is ptr into Menu`Avail array) method Edit=ViewEdit //o:Edit(ID,Name,R,C,Rs,Cs,Clr,Shadow) method ViewEdit=ViewViewEdit //o:ViewEdit(ID,Name,R,C,Rs,Cs,Clr,Shadow) method Goto=ViewGoto //o:Goto(ID,Name,R,C,Rs,Cs,Clr,Shadow) method Locate=ViewLocate //o:Locate(ID,Name,R,C,Rs,Cs,Clr,Shadow) method PreGoto=ViewPreGoto //o:PreGoto(Menu,MdId) method PostGoto=ViewPostGoto //o:PostGoto(Menu,MdId) method SetIndex=ViewSetIndex //o:SetIndex(ID,R,C,CurSize,Clr,Shadow) method SetFilter=ViewSetFilter //o:SetFilter(ID,R,C,CurSize,Clr,Shadow) method SetReport=ViewSetReport //o:SetReport(ID,WinName,R,C,CurSize,Clr,Shadow) method ModIndex=ViewModIndex //o:ModIndex(ID,WinName,R,C,CurSize,Clr,Shadow) method ModFilter=ViewModFilter //o:ModFilter(ID,WinName,R,C,CurSize,Clr,Shadow) method ModReport=ViewModReport //o:ModReport(ID,WinName,R,C,CurSize,Clr,Shadow) method VProcess=ViewVProcess //o:VProcess() method Done=ViewDone //o:Done(lRePaint) method EndViewEdit=ViewEndViewEdit //o:EndViewEdit(View,nID,Name,R,C,Rs,Cs,Clr,Shadow) endclass //***************************************************************************** // View:New() --> self // default values for this object // constructor ViewNew() ::ViewID:=0 ::MenuID:=0 ::MenuNtxID:=0 ::MenuFltID:=0 ::MenuRptID:=0 ::CanGoto:=true ::Fields:={} ::Action:={} ::Filter:={{},{},{},{}} ::Report:={{},{},{}} return(self) //***************************************************************************** // View:CreateObj() --> self // default values for this object // method function ViewCreateObj() return(object of View) //----------------------------------------------------------------------------- // GetVList() --> VList // return view list // function GetVList() return(VList) //***************************************************************************** // View:Init() --> true // dummy initialize new view object // this is not true init! You must call View:View() or View:Edit()! (need for Task:Init()) // this is need for postInitialization with user defined fnc in main program (see OExample.prg) // method function ViewInit() if Select(cBasic)==0 //for building view(s) the databases must be opened! GetLastDbf():Open() //Open /Create the databases endif ::ViewID:=++nViewID AAdd(::Filter[1]," "+ResTxt(046)+" ") AAdd(::Filter[2],"") AAdd(::Filter[3],false) AAdd(::Filter[4],false) return(true) //***************************************************************************** // View:Select(cAlias) --> true // save cAlias, for later selecting master database area, for this view. // method function ViewSelect(cAlias) local OldS:=Select() cAlias:=Upper(cAlias) ::Alias:=cAlias ::OneDbf:=GetOneDbf(cAlias) //primary index definitions select (cIFR) set filter to field->ViewID==::ViewID and field->Code=="I" //indexes DbEval({||InDbRead(self)}) ::OneDbf:NtxOpen(false) select (cIFR) //restore work area set filter to field->ViewID==::ViewID and field->Code=="F" //filters DbEval({||FiDbRead(self)}) set filter to field->ViewID==::ViewID and field->Code=="R" //reports DbEval({||ReDbRead(self)}) set filter to select (OldS) return(true) static function InDbRead(View) local d:=ListAsArray(RTrim(field->Data),v_data_sep) View:OneDbf:AddNtx(d[1],d[2],d[3],d[4]=="T",d[5]=="T") //cName,cFile,cKey,lUnique,lUser return(true) static function FiDbRead(View) local d:=ListAsArray(RTrim(field->Data),v_data_sep) AAdd(View:Filter[1],d[1]) //cName AAdd(View:Filter[2],d[2]) //cExpression AAdd(View:Filter[3],true) //lCanModify AAdd(View:Filter[4],d[3]=="T") //lMark return(true) static function ReDbRead(View) local dt:=ListAsArray(RTrim(field->Data),v_data_sep) //field->Data="cName∞cTopLine1;cTopLine2∞cShortName,cTitle,cField,cPicture,lTotal,cSubTotal;cShortName...∞cBottom1;cBottom2∞lOnlyTotals" local fs:=ListAsArray(dt[3],";") //fs:={"cShortName,cTitle,cField...",...} local a:={} //empty a=aFields AEval(fs,{|e|AAdd(a,ListAsArray(e))}) //load a=aFields AEval(a,{|e,i|if(Empty(e[4]),a[i,4]:=nil,),; e[5]:=(e[5]=="T"),; if(Empty(e[6]),a[i,6]:=nil,); }; ) AAdd(View:Report[1],dt[1]) //cName AAdd(View:Report[2],{dt[2],a,dt[4],dt[5]=="T"}) //cTop,aFields,cBottom,lOnlyTotals AAdd(View:Report[3],true) //lCanModify return(true) //***************************************************************************** // View:DefWindow(Name,R,C,Rs,Cs,Clr,Shadow) // update the window data for this object // method function ViewDefWindow(Name,R,C,Rs,Cs,Clr,Shadow) default Rs := MaxRow()-7 default Cs := MaxCol()-9 default R := (MaxRow()-Rs)/2 default C := (MaxCol()-Cs)/2 ::Form:Row := R ::Form:Col := C store value Name into ::Name store value Rs into ::Form:RowSize store value Cs into ::Form:ColSize store value Clr into ::Color store value Shadow into ::Shadow ::Form:MaxRows := ::Form:RowSize //Mask window cannot be "sizeable" ::Form:MaxCols := ::Form:ColSize ::Form:MinRows := ::Form:RowSize ::Form:MinCols := ::Form:ColSize return(true) //***************************************************************************** // View:AddBlock(cLongName,cShortName,cVarName,bBlock,bDoGet,cPicture,bWhen,bValid) --> true // save (add) block (mem_var, unstandart_field) for later rendering in this view. // method function ViewAddBlock(LongN,ShortN,VarN,Block,DoGet,Picture,When,Valid) default LongN to ShortN default VarN to ShortN VarN:=Upper(VarN) if( At("->",VarN)==0, VarN:="MEMORY->"+VarN, ) AAdd(::Fields,{LongN,ShortN,VarN,Block,Picture,When,Valid,,,DoGet}) //len=10 HelpAssoc(VarN,ShortN,HelpReserved(,+1)) //code block can be unique for every View object return(true) //***************************************************************************** // View:AddMemo(cLongName,cShortName,cField,bWhen,bValid,nRowSize,nColSize) --> true // save (add) memo field for later rendering in this view. // method function ViewAddMemo(cLongN,cShortN,cField,bWhen,bValid,nRowSize,nColSize) local f,s,dbf,i cField:=Upper(cField) f:=GetField(cField) s:=GetSelect(cField); if Empty(s) or s=="FIELD"; s:=::Alias; endif dbf:=GetOneDbf(s) i:=AScan(dbf:Struc,{|e|e[1]==f}) default cShortN to cField default cLongN to cShortN default nRowSize to Int(MaxRow()/3) default nColSize to Int(MaxCol()/2) default bWhen to dbf:PreBlock[i] default bValid to dbf:PostBlock[i] AAdd(::Fields,{cLongN,cShortN,s,f,,bWhen,bValid,nRowSize,nColSize}) //len=9 if !ChangeAssoc(s+"->"+f,cShortN,) Abort("Association cannot be changed.") endif return(true) //***************************************************************************** // View:AddField(cLongName,cShortName,cField,cPicture,bWhen,bValid) --> true // save (add) view field for later rendering in this view. // method function ViewAddField(cLongN,cShortN,cField,cPicture,bWhen,bValid) local f,s,dbf,i cField:=Upper(cField) f:=GetField(cField) s:=GetSelect(cField); if Empty(s) or s=="FIELD"; s:=::Alias; endif dbf:=GetOneDbf(s) i:=AScan(dbf:Struc,{|e|e[1]==f}) default cShortN to cField default cLongN to cShortN default cPicture to dbf:Pict[i] default bWhen to dbf:PreBlock[i] default bValid to dbf:PostBlock[i] AAdd(::Fields,{cLongN,cShortN,s,f,cPicture,bWhen,bValid}) //len=7 if !ChangeAssoc(s+"->"+f,cShortN,) Abort("Association cannot be changed.") endif return(true) //***************************************************************************** // View:AddAction(nKey,bProcedure,cInfo) --> true // add new hot-key action into this view. // method function ViewAddAction(nKey,bProcedure,cInfo) default cInfo to "" AAdd(::Action,{nKey,bProcedure,nil,cInfo}) //cInfo is short text that will be added into dialogue line return(true) //***************************************************************************** // View:AddFilter(cName,cExpr,lMark) --> true // add new filter expression into this view. // method function ViewAddFilter(cName,cExpr,lMark) local nIndex:=AScan(::Filter[3],true) default lMark:=false ATrueIns(::Filter[1],nIndex," "+AllTrim(cName)+" ") //Name ATrueIns(::Filter[2],nIndex,cExpr) //Expression ATrueIns(::Filter[3],nIndex,false) //CanModify ATrueIns(::Filter[4],nIndex,lMark) //Colored/Hidden return(true) //***************************************************************************** // View:AddRAll(cName,cTop,aFields,cBottom,lOnlyTotals) --> true // add (save) new ALL report into this view. // method function ViewAddRAll(cName,cTop,aFields,cBottom,lOnlyTotals) nIndex:=AScan(::Report[3],true) default cTop to "" default cBottom to "" default lOnlyTotals to false ATrueIns(::Report[1],nIndex," "+AllTrim(cName)+" ") //Name ATrueIns(::Report[2],nIndex,{cTop,aFields,cBottom,lOnlyTotals}) //Expression ATrueIns(::Report[3],nIndex,false) //CanModify return(true) //***************************************************************************** // View:AddReport(cName,lOnlyTotals) --> true // create new report arrays for this view // method function ViewAddReport(cName,lOnlyTotals) default lOnlyTotals:=false nIndex:=AScan(::Report[3],true) //Save index for currently builded report ATrueIns(::Report[1],nIndex," "+AllTrim(cName)+" ") //Name ATrueIns(::Report[2],nIndex,{"",{},"",lOnlyTotals}) //Empty Expression={cTop,aFields,cBottom,lOnlyTotals} ATrueIns(::Report[3],nIndex,false) //CanModify fill empty nIndex with Len(::Report[3]) //set end_of_array return(true) //***************************************************************************** // View:AddRTop(cTop) --> true // add all top lines into this array // method function ViewAddRTop(cTop) ::Report[2,nIndex,1]:=cTop return(true) //***************************************************************************** // View:AddRField(cTitle,cField,cPicture,lTotal,cSubTotal) --> true // add (save) new field report into this view. // method function ViewAddRField(cTitle,cField,cPicture,lTotal,cSubTotal) local i cField:=Upper(cField) //work around field if At("->",cField)==0 or SubStr(cField,5)=="FIELD" cField:=::Alias+"->"+SubStr(cField,At("->",cField)) endif if !Empty(cSubTotal) cSubTotal:=Upper(cSubTotal) //work around subtotal if At("->",cSubTotal)==0 or SubStr(cSubTotal,5)=="FIELD" cSubTotal:=::Alias+"->"+SubStr(cSubTotal,At("->",cSubTotal)) endif endif if cTitle==nil or cPicture==nil if (i:=AScan(::Fields,{|e|e[3]+"->"+e[4]==cField}))>0 //find cField in View default cTitle to ::Fields[i,2] default cPicture to ::Fields[i,5] endif endif AAdd(::Report[2,nIndex,2],{"",cTitle,cField,cPicture,lTotal,cSubTotal}) return(true) //***************************************************************************** // View:AddRBottom(cBottom) --> true // add bottom lines into this array // method function ViewAddRBottom(cBottom) ::Report[2,nIndex,3]:=cBottom return(true) //***************************************************************************** // View:View(nID,Name,R,C,Rs,Cs,Clr,Shadow) --> true // virtual view process, last initialization // method function ViewView(nID,Name,R,C,Rs,Cs,Clr,Shadow) local V:=::Copy() //now we must to create copy of view object //default values V:CanEdit:=false V:CanAppend:=false V:Color:=m->Color:View V:EndViewEdit(self,nID,Name,R,C,Rs,Cs,Clr,Shadow) return(V:Process()) //***************************************************************************** // View:Edit(nID,Name,R,C,Rs,Cs,Clr,Shadow) --> nil // virtual edit process, last initialization // method function ViewEdit(nID,Name,R,C,Rs,Cs,Clr,Shadow) local V:=::Copy() //now we must to create copy of view object V:EndViewEdit(self,nID,Name,R,C,Rs,Cs,Clr,Shadow) return(V:Process()) //***************************************************************************** // View:ViewEdit(nID,Name,R,C,Rs,Cs,Clr,Shadow) --> nil // virtual view_or_edit process, no AClone() of this object // method function ViewViewEdit(nID,Name,R,C,Rs,Cs,Clr,Shadow) ::EndViewEdit(self,nID,Name,R,C,Rs,Cs,Clr,Shadow) return(::Process()) //***************************************************************************** // V:=View:Copy() // creating copy of view object // method function ViewCopy() local V:=::CreateObj() //_________________Loc_________________ V:Row:=::Row // 3 V:Col:=::Col // 4 //_________________Box_________________ V:Name:=::Name // "" V:RowSize:=::RowSize // MaxRow()-7 V:ColSize:=::ColSize // MaxCol()-9 V:Color:=::Color // m->Color`Edit V:Shadow:=::Shadow // true //_________________Window______________ V:ID:=::ID // 0 V:WRow:=::WRow // 3 V:WCol:=::WCol // 4 V:WRowSize:=::WRowSize // MaxRow()-7 V:WColSize:=::WColSize // MaxCol()-9 V:IsMax:=::IsMax // false V:IsMin:=::IsMin // false V:MaxRows:=::MaxRows // MaxRow()-3 V:MaxCols:=::MaxCols // MaxCol()-1 V:MinRows:=::MinRows // 1 V:MinCols:=::MinCols // 5 V:UpFlag:=::UpFlag // false V:Screen:=::Screen // "" V:UpScreen:=::UpScreen // "" V:BkScreen:=::BkScreen // "" V:RCInfo:=::RCInfo // "" V:InfoMsg:=::InfoMsg // "" //V:Frame:=::Frame // (object of Frame) ƒ> € can not be copyied € //_________________Task________________ V:IsDead:=::IsDead // false V:DoneBlock:=::DoneBlock // {||true} //_________________Browse______________ V:CanShowSkip:=::CanShowSkip // false V:CanEdit:=::CanEdit // true V:CanAppend:=::CanAppend // true V:CanSwap:=::CanSwap // true V:CanSkip:=::CanSkip // true V:FormActive:=::FormActive // false V:Direction:=::Direction // K_RIGHT V:QuickEdit:=::QuickEdit // true V:SetConfirm:=::SetConfirm // Set(_SET_CONFIRM) V:AddMsg:=::AddMsg // "" V:InsBlock:=::InsBlock // {|o|nil} V:DelBlock:=::DelBlock // {|o|nil} V:InfoBlock:=::InfoBlock // {|o|nil} V:GetList:=AClone(::GetList) // {} V:DoGetList:=AClone(::DoGetList) //{} V:DelGet:=AClone(::DelGet) // {} V:DelDoGet:=AClone(::DelDoGet) // {} V:Tb:=::Tb // nil V:PreSkip:=::PreSkip V:PostSkip:=::PostSkip V:Freeze:=::Freeze // 0 V:FormTop:=::FormTop // 1 V:Form:=(object of Window) // (object of Window) ƒƒ> see Browse:PostInit() V:Form:Row:=::Form:Row V:Form:Col:=::Form:Col V:Form:RowSize:=::Form:RowSize V:Form:ColSize:=::Form:ColSize V:Form:MaxRows:=::Form:MaxRows V:Form:MaxCols:=::Form:MaxCols V:Form:MinRows:=::Form:MinRows V:Form:MinCols:=::Form:MinCols V:SetUp:=::SetUp // false //_________________DBrowse_____________ V:Alias:=::Alias // "" V:RecNo:=::RecNo // 1 V:IndexNo:=::IndexNo // 0 V:FilterNo:=::FilterNo // 0 V:FilterExp:=::FilterExp // "" V:FilterBExp:=::FilterBExp // {||...} V:FilterMark:=::FilterMark // false V:InsBlock:=::InsBlock // {|o|o``DoInsert()} V:DelBlock:=::DelBlock // {|o|o``DoDelete()} V:InfoBlock:=::InfoBlock // {|o|o``DoInfo()} //_________________View________________ V:ViewID:=::ViewID // 0 V:MenuID:=::MenuID // 0 V:MenuNtxID:=::MenuNtxID // 0 V:MenuFltID:=::MenuFltID // 0 V:MenuRptID:=::MenuRptID // 0 V:CanGoto:=::CanGoto // true V:Fields:=AClone(::Fields) // {} V:Action:=AClone(::Action) // {} // V:Filter:=::Filter // {{},{},{},{}} ƒø must be the same // V:Report:=::Report // {{},{},{}} √> as parent, // V:OneDbf:=::OneDbf // object of OneDbf ƒŸ see EndViewInit() return(V) //***************************************************************************** // V:EndViewEdit(View,nID,Name,R,C,Rs,Cs,Clr,Shadow) --> nil // post initialization before dbrowse_process // method function ViewEndViewEdit(View,nID,Name,R,C,Rs,Cs,Clr,Shadow) local Ch store value nID into ::MenuID ::Filter:=View:Filter //array pointer ⁄ƒƒƒø all threaded object ::Report:=View:Report //array pointer ≥ ! ≥ MUST HAVE THE SAME ::OneDbf:=View:OneDbf //object pointer ¿ƒƒƒŸ index, filter and report Ch:=::FilterNo+1 //get new filter index ::FilterExp:=::Filter[2,Ch] //save new filter expression !!! ::FilterBExp:=if(Empty(::Filter[2,Ch]),{||false},&("{||"+::Filter[2,Ch]+"}")) //...as code block ::FilterMark:=::Filter[4,Ch] //flag to_Mark (true) / to_Hide (false) ::super(DBrowse):Init(Name,R,C,Rs,Cs,Clr,Shadow) AEval(::Fields,{|e|Build(self,e)}) AAdd(VList,self) //save view into view_list return(true) //----------------------------------------------------------------------------- // V::Build(V,e) --> true // build one editable item for DBrowse // e={cLongName,cShortName,cAlias/cVarName,cField/bBlock,cPicture,bWhen,bValid,nRowSize,nColSize,bDoGet} // -1------- -2-------- -3------------- -4----------- -5------ -6--- -7---- -8------ -9------ -10--- // static function Build(V,e) local ln:=Len(e) do case case ln=10; BuildBlock(V,e[1],e[2],e[3],e[4],e[5],e[6],e[7],e[10]) //LongName,ShortName,VarName,Block,Picture,When,Valid,DoGet case ln=9; BuildMemo(V,e[1],e[2],e[3],e[4],e[5],e[6],e[7],e[8],e[9]) //LongName,ShortName,Alias, Field,Picture,When,Valid,RowSize,ColSize case ln=7; BuildField(V,e[1],e[2],e[3],e[4],e[5],e[6],e[7]) //LongName,ShortName,Alias, Field,Picture,When,Valid endcase return(true) //----------------------------------------------------------------------------- // V::BuildBlock(LongN,ShortN,VarName,Block,Picture,When,Valid,DoGet) --> true // build one editable item for DBrowse // static function BuildBlock(V,LongN,ShortN,VarName,Block,Picture,When,Valid,DoGet) local g SetColor(V:Color) g:=GetNew(0,0,Block,VarName) g:Picture:=Picture g:PreBlock:=When g:PostBlock:=Valid g:Cargo:=Array(nLenCargo) g:Cargo[nLongName]:=LongN g:Cargo[nShortName]:=ShortN g:Cargo[nAlias]:=V:Alias V:AddGet(g,DoGet) return(true) //----------------------------------------------------------------------------- // V::BuildMemo(LongN,ShortN,Alias,Field,Picture,When,Valid,RowSize,ColSize) --> true // build memo_get for DBrowse // static function BuildMemo(V,LongN,ShortN,Alias,Field,Picture,When,Valid,RowSize,ColSize) local g default When to {||true} default Valid to {||true} SetColor(V:Color) g:=GetNew(0,0,{||ResTxt(134)},Alias+"->"+Field) g:Picture:=Picture g:Cargo:=Array(nLenCargo) g:Cargo[nLongName]:=LongN g:Cargo[nShortName]:=ShortN g:Cargo[nAlias]:=Alias g:PostBlock:={|g,lEdit|MemoPostBlock(V,g,lEdit,FieldWBlock(Field,Select(Alias)),When,Valid,RowSize,ColSize)} V:AddGet(g) return(true) static function MemoPostBlock(V,g,lEdit,Block,When,Valid,RowSize,ColSize) local x local l:=LastKey() if l==10 or l==13 or V:QuickEdit and 32<=l and l<=126 if Eval(When,g,lEdit) and ((!lEdit)or((g:Cargo[nAlias])->(NetRLock(true)))) SaveDOut(V:AddMsg) if lEdit; x:=Eval(Block); endif ReadHelpVar(g:Name) Memo(Block,lEdit,,,,RowSize,ColSize) ReadHelpVar("") RestDOut() g:SetFocus() if lEdit and (x<>Eval(Block)) g:OverStrike(Left(ResTxt(134),1)) //set non-assignable g:changed onto true endif Eval(Valid,g,lEdit) g:KillFocus() if lEdit; (g:Cargo[nAlias])->(DbUnLock()); endif else if 32<=l and l<=126; InKeyWait(); endif //remove key from queue endif return(false) endif return(true) //----------------------------------------------------------------------------- // V::BuildField(LongN,ShortN,Alias,Field,Picture,When,Valid) --> true // build field_get for DBrowse // static function BuildField(V,LongN,ShortN,Alias,Field,Picture,When,Valid) local g SetColor(V:Color) g:=GetNew(0,0,FieldWBlock(Field,Select(Alias)),Alias+"->"+Field) g:Picture:=Picture g:PreBlock:=When g:PostBlock:=Valid g:Cargo:=Array(nLenCargo) g:Cargo[nLongName]:=LongN g:Cargo[nShortName]:=ShortN g:Cargo[nAlias]:=Alias V:AddGet(g) return(true) //***************************************************************************** // View:Goto(ID,Name,R,C,Rs,Cs,Clr,Shadow) --> true // go to record // method function ViewGoto(ID,Name,R,C,Rs,Cs,Clr,Shadow) local n local Lt:=GetLastView(self) local object Box of Box if Empty(Lt); Lt:=self; endif default Name to "" default R to Lt:Row default C to Lt:Col+2 default Rs to 1 default Cs to Len(ResTxt(050))+10 default Clr to Lt:Color object Box of Box Box:GoodInit(Name,R,C,Rs,Cs,-1,Clr,Shadow) n:=EditIt(RecNo(),ResTxt(050),,Box:Row,Box:Col,Clr) if n<RecNo(); Lt:Tb:RowPos:=1; endif do case case n<1; go top case n>LastRec(); go bottom otherwise; go n endcase SetLastKey(0) Lt:RecNo:=RecNo() Lt:VPaint() return(true) //***************************************************************************** // View:Locate(ID,Name,R,C,Rs,Cs,Clr,Shadow) --> true // locate for record // method function ViewLocate(ID,Name,R,C,Rs,Cs,Clr,Shadow) local n,cc,g,IsMemo:=false local Lt:=GetLastView(self) local object Box of Box if Empty(Lt); Lt:=self; endif g:=Lt:GetList[Lt:Tb:ColPos] cc:=Transform(Eval(g:block),g:Picture) if cc==ResTxt(134); IsMemo:=true; cc:=Space(40); endif default Name to "" default R to Lt:Row default C to Lt:Col+2 default Rs to 1 default Cs to Len(cc)+Len(ResTxt(177))+Len(g:Cargo[nShortName])+4 default Clr to Lt:Color object Box of Box Box:GoodInit(Name,R,C,Rs,Cs,-1,Clr,Shadow) cc:=AllTrim(EditIt(cc,ResTxt(177)+" "+g:Cargo[nShortName],,Box:Row,Box:Col,Clr)) n:=RecNo() if !Empty(cc) and LastKey()<>K_ESC SaveDOut(ResTxt(176)) DbSkip() if IsMemo cc:="{||!('"+cc+"' $ "+g:Name+")}" DbEval({||nil},,&(cc)) else DbEval({||nil},,{||!(cc $ Transform(Eval(g:block),g:picture))}) endif if !Eof() refresh table else go n Alert(ResTxt(178)) endif RestDOut() endif SetLastKey(0) Lt:RecNo:=RecNo() Lt:VPaint() return(true) //***************************************************************************** // View:PreGoto(Menu,MdId) --> true // prevalidation for View:Goto() // method function ViewPreGoto(Menu,MdId) if Empty(GetLastView(self)) Menu:DisableItem(((Menu:GetMD(MdId)):Data[3]):ID, false) Menu:DisableItem(((Menu:GetMD(MdId)):Data[4]):ID, false) else Menu:EnableItem(((Menu:GetMD(MdId)):Data[3]):ID, false) Menu:EnableItem(((Menu:GetMD(MdId)):Data[4]):ID, false) endif return(true) //***************************************************************************** // View:PostGoto(Menu,MdId) --> true // postvalidation for View:Goto() // method function ViewPostGoto(Menu,MdId) Menu:EnableItem(((Menu:GetMD(MdId)):Data[3]):ID, false) Menu:EnableItem(((Menu:GetMD(MdId)):Data[4]):ID, false) return(true) //***************************************************************************** // View:SetIndex(nID,R,C,CurSize,Clr,Shadow) --> true // select index and set it // method function ViewSetIndex(ID,R,C,CurSize,Clr,Shadow) local Ch,LastView,i local arl:={} local ar:={" "+ResTxt(045)+" "} local object Mnu of Mnu AEval(::OneDbf:Ntx,{|e|AAdd(ar," "+e[1])}) //cName GetArl(self,ar,@arl,@LastView) //build arl & get LastView i:=1 AEval(::OneDbf:Ntx,{|e|i++,if(Empty(e[3]),arl[i]:=false,nil)}) Mnu:Init("",R,C,CurSize,ar,arl,Clr,Shadow) Ch:=Mnu:Process() Mnu:Done() if Ch>0 set order to (Ch-1) LastView:IndexNo:=(Ch-1) //save index order into curent view (last active task) LastView:Tb:RowPos:=1 LastView:Tb:Configure() endif if LastKey()==K_ESC and SetQuickEsc(); StuffKey(K_ESC); endif return(true) //----------------------------------------------------------------------------- // View::GetArl(ar,@arl,@LastView) --> true // build paralel array of logical values that specify the selectable menu items // and look for last running view object // static function GetArl(View,ar,arl,LastView) arl:=Array(Len(ar)) //arl=array for enable/disable items in ar LastView:=GetLastView(View) AFill(arl,LastView<>nil) return(true) //----------------------------------------------------------------------------- // View::GetLastView() --> LastView/nil // look for last running view object // static function GetLastView(View) local Lt:=SetLastTask() if !Empty(Lt) and Lt:ClassName==View:ClassName and Lt:ViewID==View:ViewID return(Lt) endif return(nil) //***************************************************************************** // View:SetFilter(nID,R,C,CurSize,Clr,Shadow) --> true // select filter from mnu and set it // method function ViewSetFilter(nID,R,C,CurSize,Clr,Shadow) local Ch,LastView,arl local ar:=::Filter[1] local object Mnu of Mnu GetArl(self,ar,@arl,@LastView) //build arl & get LastView Mnu:Init("",R,C,CurSize,ar,arl,Clr,Shadow) Ch:=Mnu:Process() Mnu:Done() if Ch>0 and ( !(LastView:FilterExp==::Filter[2,Ch]) or ; !(LastView:FilterMark==::Filter[4,Ch]) ) LastView:FilterNo:=Ch-1 //save new filter index LastView:FilterExp:=::Filter[2,Ch] //save new filter expression LastView:FilterBExp:=if(Empty(::Filter[2,Ch]),{||false},&("{||"+::Filter[2,Ch]+"}")) //...as code block LastView:FilterMark:=::Filter[4,Ch] //flag to_Mark (true) / to_Hide (false) LastView:UpFilter() go top LastView:Tb:RowPos:=1 LastView:Tb:Configure() endif if LastKey()==K_ESC and SetQuickEsc(); StuffKey(K_ESC); endif return(true) //***************************************************************************** // View:SetReport(nID,WinName,R,C,CurSize,Clr,Shadow) --> true // select and process selected report // method function ViewSetReport(nID,WinName,R,C,CurSize,Clr,Shadow) local Ch,Dt,aF local TaskID,i local Ct:=self //CurrentTask local ar:=Ct:Report[1] local object Mnu of Mnu local object Report of Report if Empty(ar); Alert(ResTxt(080)); return(false); endif Mnu:Init("",R,C,CurSize,ar,,Clr,Shadow) Ch:=Mnu:Process() Mnu:Done() if Ch>0 if( Empty(Ct:=GetLastView(self)), Ct:=self, ) Dt:=Ct:Report[2,Ch] i:=AllTrim(ar[Ch]) //strip number from nemu item for window name for report. if Left(i,1)=="~" and IsDigit(SubStr(i,2)) and SubStr(i,3,1)=="."; i:=SubStr(i,4); endif //ƒƒŸ e.g: "~1.The report" --> "The report" Report:Init(StrTran(ResTxt(044),"~")+":"+i+": "+WinName) aF:=AClone(Dt[2]) AEval(aF,{|e|ATrueDel(e,1)}) Report:AddData(Dt[1],aF,Dt[3],Dt[4]) //cTop,aFields,cBottom,lOnlyTotals Report:Alias:=Ct:Alias Report:IndexNo:=Ct:IndexNo if !Ct:FilterMark Report:FilterNo:=Ct:FilterNo Report:FilterExp:=Ct:FilterExp endif SetLastTask(nil) //clear last task, need for repaint; save info for restart task, see c_Task.prg endif if LastKey()==K_ESC and SetQuickEsc(); StuffKey(K_ESC); endif return(true) //***************************************************************************** // View:ModIndex(ID,WinName,R,C,CurSize,Clr,Shadow) --> true // virtual modify index process, last initialization // method function ViewModIndex(ID,WinName,R,C,CurSize,Clr,Shadow) local arl:={false} local ar:={" "+ResTxt(045)+" "} local object Mnu of Mnu if LogSet()<>1 Alert(ResTxt(072)+";"+ResTxt(071)) return(false) endif default R to Row() default C to Col() ::MenuNtxID:=ID //used in EditIndex! (thread task must temporary disable own menu_item!) AEval(::OneDbf:Ntx,{|e|AAdd(ar," "+e[1]),AAdd(arl,e[5])}) //cName,lUser Mnu:InsBlock:={|Mnu|InsIndex(self,WinName,Clr,Shadow)} Mnu:DelBlock:={|Mnu|DelIndex(self,Mnu,R,C,CurSize,ar,arl)} Mnu:CanAppend:=true if Empty(ar) if InsIndex(self,WinName,Clr,Shadow) PauseKey(0) //remove nSwapTask from keyboard queue else SetLastKey(0) return(true) endif else Mnu:Init("",R,C,CurSize,ar,arl) if AScan(arl,true)==0; StuffKey(K_INS); endif //for empty menu do append if Mnu:Process()>0; EditIndex(self,Mnu:Choice-1,false,WinName,Clr,Shadow); endif Mnu:Done() endif do case case LastKey()==nSwapTask; SetLastKey(K_ENTER) case LastKey()==K_ESC and SetQuickEsc(); StuffKey(K_ESC) endcase return(true) static function InsIndex(View,WinName,Clr,Shadow) local i,cName,cFile if Alert(ResTxt(104),ResTxt(123))<>1; return(false); endif i:=Len(View:OneDbf:Ntx)+1 cName:="~"+NTrim(i)+"." cFile:=cNtxFile+StrTran(Transform(View:ViewID,"99")+Transform(i,"99")," ","0") //cFile(Name) for new index View:OneDbf:AddNtx(cName,cFile,"",false,true) //cName,cFile,cKey,lUnique,lUser EditIndex(View,i,true,WinName,Clr,Shadow) //append into cIFR SetMenuCmd(0) //force restart task (in menu) StuffKeys(Chr(nSwapTask)+Chr(K_END)) //exit from Mnu:Process() & restart task, go end of line. return(true) static function DelIndex(View,Mnu,R,C,CurSize,ar,arl) local s:=Select() local i:=Mnu:Choice-1 if AScan(Mnu:SelItems,true)==0; return(false); endif if Alert(ResTxt(105),ResTxt(123))<>1; return(false); endif select (cIFR) if FindIfrItem(View,i,"I",false) //find i-th index item in cIFR net delete continue endif select (s) ATrueDel(View:OneDbf:Ntx,i) ATrueDel(Mnu:Items,Mnu:Choice) ATrueDel(Mnu:SelItems,Mnu:Choice) Mnu:Choice:=Min(Mnu:Choice,Len(ar)) Mnu:Hide() Mnu:Init("",R,C,CurSize,ar,arl) return(true) static function EditIndex(View,i,lAppend,WinName,Clr,Shadow) //create new task, done menu, go into new task! local MaxC:=0 local cName:=PadR(View:OneDbf:Ntx[i,1],nLenIFRName) local cKey:=PadR(View:OneDbf:Ntx[i,3],nLenIFRData-nLenIFRName-20) local lUnique:=false local object Info of Info //info-help task local object AB of ABrowse //new task local ABName:=if(lAppend,ResTxt(059),ResTxt(041))+" "+Lower(ResTxt(042)) AEval(View:Fields,{|e|if(!Empty(e[4]) and ValType(e[4])=="C",MaxC:=Max(MaxC,Len(e[3])+Len(e[4])),nil)}) * Info:Buff+=ResTxt(064)+cr_lf+Replicate("-",Len(ResTxt(064)))+cr_lf Info:Buff+="Character, Date, Logical, Numeric"+cr_lf+cr_lf * Info:Buff+=ResTxt(066)+cr_lf+Replicate("-",Len(ResTxt(066)))+cr_lf Info:Buff+="Trans(field->XXX,)+Trans(field->YYY,)"+cr_lf+cr_lf * Info:Buff+=ResTxt(067)+cr_lf+Replicate("-",Len(ResTxt(067)))+cr_lf Info:Buff+=View:Alias+cr_lf+cr_lf * Info:Buff+=ResTxt(068)+cr_lf+Replicate("-",Len(ResTxt(068)))+cr_lf AEval(View:Fields,{|e,p|if(!Empty(e[4]) and ValType(e[4])=="C",(p:=Lower(e[3]+"->"+e[4]),Info:Buff+=PadR(Type(p)+":"+p,MaxC+5)),nil)}) Info:Buff+=cr_lf+cr_lf * Info:Buff+=ResTxt(069)+cr_lf+Replicate("-",Len(ResTxt(069)))+cr_lf Info:Buff+=v_fnc_info+cr_lf+cr_lf * Info:Buff+=Replicate("-",10)+" "+ResTxt(005)+" "+Replicate("-",10) Info:Init(StrTran(ResTxt(057)+" "+Lower(ResTxt(042)),"~")+": "+WinName) Info:Row:=2 Info:RowSize:=MaxRow()-8 * AB:CanSwap:=false AB:FormActive:=true AB:CanAppend:=false AB:MoreRecords:=false AB:Init(StrTran(ABName,"~")+": "+WinName,,,,,Clr,Shadow) AB:DoneBlock:={|o|DoneIndex(View,o,i,lAppend,cName,cKey,lUnique,Info)} AB:AddBlock(,ResTxt(056),"SYS:->IDX_NAME",{|x|if(nil==x,cName,cName:=x)}) AB:AddBlock(,ResTxt(061),"SYS:->IDX_KEY", {|x|if(nil==x,cKey,cKey:=x)},,"@S"+NTrim(nLenIFRName+10)) AB:AddBlock(,ResTxt(063),"SYS:->IDX_UNIQ",{|x|if(nil==x,lUnique,lUnique:=x)},,"@!") AB:PostInit() AB:Row:=MaxRow()-5 GetActiveMenu():DisableItem(View:MenuNtxID) //new task !!! SetLastTask(nil) //must be, because I want do restart this (new) task, not last task. return(true) static function DoneIndex(View,AB,i,lAppend,cName,cKey,lUnique,Info) //Save values into: View`OneDbf & cIFR local x,s:="" local OldS:=Select() begin break select (View:Alias) x:=&(cKey) recover break select (OldS) if Empty(SetLastTask()); AB:Top(false); endif if AB:ID<>SetLastTask():ID; AB:Top(false); endif if Alert(ResTxt(096)+";"+ResTxt(058)+" "+Lower(ResTxt(061)),ResTxt(124))==1 AB:Paint(false) ATrueDel(View:OneDbf:Ntx,i) if !Info:IsDead; Info:Done(); endif GetActiveMenu():EnableItem(View:MenuNtxID) return(true) else return(false) endif end break x:=AClone(View:OneDbf:Ntx[i]) //working copy of current index x[1]:=AllTrim(cName) x[3]:=AllTrim(cKey) x[4]:=lUnique AEval(x,{|e|s+=v_data_sep+Transform(e,)}) s:=SubStr(s,Len(v_data_sep)+1) select (View:Alias) DbClearIndex() CreateIndex(x,true) //x=={cName,cFile,cKey,lUnique}, lContinue if NetErr() and lAppend ATrueDel(View:OneDbf:Ntx,i) else //index created select (cIFR) if lAppend net append blank continue else FindIfrItem(View,i,"I",true) net rlock continue endif if NetErr() and lAppend ATrueDel(View:OneDbf:Ntx,i) else //record is ready field->ViewID:=View:ViewID field->Code:="I" field->Data:=s commit net unlock View:OneDbf:Ntx[i]:=x //save info into current Ntx data structure endif endif View:OneDbf:NtxOpen(false) if !Info:IsDead; Info:Done(); endif GetActiveMenu():EnableItem(View:MenuNtxID) select (OldS) return(true) static function FindIfrItem(View,i,Cd,lCanAppend) //Cd (Code) can be "I","F","R" local n,c if Cd=="I" c:=View:OneDbf:Ntx[i,1] //cName elseif Cd=="F" c:=View:Filter[1,i] //cName else c:=View:Report[1,i] //cName endif n:=Len(c) locate for field->ViewID==View:ViewID and field->Code==Cd and Left(field->Data,n)==c if !Found() and lCanAppend net append blank continue if NetErr(); Abort("Can't find this item in database!"); endif field->ViewID:=View:ViewID field->Code:=Cd net unlock endif return(Found()) //***************************************************************************** // View:ModFilter(ID,WinName,R,C,CurSize,Clr,Shadow) --> true // virtual modify filter process, last initialization // method function ViewModFilter(ID,WinName,R,C,CurSize,Clr,Shadow) local Ch local ar:=::Filter[1] local ard:=::Filter[2] local arl:=::Filter[3] local arm:=::Filter[4] local object Mnu of Mnu if LogSet()<>1 if Alert(ResTxt(072)+";"+ResTxt(075)+" "+Lower(ResTxt(054))+" "+ResTxt(076),ResTxt(123))<>1 return(false) endif endif default R to Row() default C to Col() ::MenuFltID:=ID //used in EditFilter! (thread task must temporary disable own menu_item!) Mnu:InsBlock:={|Mnu|InsFilter(self,WinName,Clr,Shadow)} Mnu:DelBlock:={|Mnu|DelFilter(self,Mnu,R,C,CurSize,ar,arl)} Mnu:CanAppend:=true if Empty(ar) if InsFilter(self,WinName,Clr,Shadow) PauseKey(0) //remove nSwapTask from keyboard queue else SetLastKey(0) return(true) endif else Mnu:Init("",R,C,CurSize,ar,arl) if AScan(arl,true)==0; StuffKey(K_INS); endif //for empty menu do append if Mnu:Process()>0; EditFilter(self,Mnu:Choice,false,WinName,Clr,Shadow); endif Mnu:Done() endif do case case LastKey()==nSwapTask; SetLastKey(K_ENTER) case LastKey()==K_ESC and SetQuickEsc(); StuffKey(K_ESC) endcase return(true) static function InsFilter(View,WinName,Clr,Shadow) local i,cName,cFile if Alert(ResTxt(104),ResTxt(123))<>1; return(false); endif i:=Len(View:Filter[1])+1 cName:="~"+NTrim(i-1)+"." AAdd(View:Filter[1],cName) AAdd(View:Filter[2],"") AAdd(View:Filter[3],true) AAdd(View:Filter[4],false) EditFilter(View,i,true,WinName,Clr,Shadow) //append into cIFR & View`Filter SetMenuCmd(0) //force restart task (in menu) StuffKeys(Chr(nSwapTask)+Chr(K_END)) //exit from Mnu:Process() & restart task, go end of line. return(true) static function DelFilter(View,Mnu,R,C,CurSize,ar,arl) local x local s:=Select() local i:=Mnu:Choice if AScan(Mnu:SelItems,true)==0; return(false); endif if Alert(ResTxt(105),ResTxt(123))<>1; return(false); endif repeat if (x:=LogSet())==1 //delete the filter on disk select (cIFR) if FindIfrItem(View,i,"F",false) net delete continue endif select (s) endif until x==1 or Alert(ResTxt(072)+";"+ResTxt(074),ResTxt(125))<>1 IEval(4,{|j|ATrueDel(View:Filter[j],i)}) Mnu:Choice:=Min(Mnu:Choice,Len(ar)) Mnu:Hide() Mnu:Init("",R,C,CurSize,ar,arl) return(true) static function EditFilter(View,i,lAppend,WinName,Clr,Shadow) //create new task, done menu, go into new task! local MaxC:=0 local cName:=PadR(LTrim(View:Filter[1,i]),nLenIFRName) local cExpr:=PadR(LTrim(View:Filter[2,i]),nLenIFRData-nLenIFRName-20) local lMark:=View:Filter[4,i] local object Info of Info //info-help task local object AB of ABrowse //new task local ABName:=if(lAppend,ResTxt(059),ResTxt(041))+" "+Lower(ResTxt(043)) AEval(View:Fields,{|e|if(!Empty(e[4]) and ValType(e[4])=="C",MaxC:=Max(MaxC,Len(e[3])+Len(e[4])),nil)}) * Info:Buff+=ResTxt(065)+cr_lf+Replicate("-",Len(ResTxt(065)))+cr_lf Info:Buff+="Logical"+cr_lf+cr_lf * Info:Buff+=ResTxt(066)+cr_lf+Replicate("-",Len(ResTxt(066)))+cr_lf Info:Buff+='DtoC(field->XXX)>="31.10.91"'+cr_lf+cr_lf * Info:Buff+=ResTxt(067)+cr_lf+Replicate("-",Len(ResTxt(067)))+cr_lf Info:Buff+=View:Alias+cr_lf+cr_lf * Info:Buff+=ResTxt(068)+cr_lf+Replicate("-",Len(ResTxt(068)))+cr_lf AEval(View:Fields,{|e,p|if(!Empty(e[4]) and ValType(e[4])=="C",(p:=Lower(e[3]+"->"+e[4]),Info:Buff+=PadR(Type(p)+":"+p,MaxC+5)),nil)}) Info:Buff+=cr_lf+cr_lf * Info:Buff+=ResTxt(069)+cr_lf+Replicate("-",Len(ResTxt(069)))+cr_lf Info:Buff+=v_fnc_info+cr_lf+cr_lf * Info:Buff+=Replicate("-",10)+" "+ResTxt(005)+" "+Replicate("-",10) Info:Init(StrTran(ResTxt(057)+" "+Lower(ResTxt(043)),"~")+": "+WinName) Info:Row:=2 Info:RowSize:=MaxRow()-8 * AB:CanSwap:=false AB:FormActive:=true AB:CanAppend:=false AB:MoreRecords:=false AB:Init(StrTran(ABName,"~")+": "+WinName,,,,,Clr,Shadow) AB:DoneBlock:={|o|DoneFilter(View,o,i,lAppend,cName,cExpr,lMark,Info)} AB:AddBlock(,ResTxt(056),"SYS:->FLT_NAME",{|x|if(nil==x,cName,cName:=x)}) AB:AddBlock(,ResTxt(062),"SYS:->FLT_EXPR",{|x|if(nil==x,cExpr,cExpr:=x)},,"@S"+NTrim(nLenIFRName+10)) AB:AddBlock(,ResTxt(181),"SYS:->FLT_PROP",{|x|if(!Empty(x),lMark:=!lMark,)," "+if(lMark,ResTxt(182),ResTxt(183))+" "},{|AB|DoGetMark(AB)}) AB:PostInit() AB:Row:=MaxRow()-5 GetActiveMenu():DisableItem(View:MenuFltID) //new task !!! SetLastTask(nil) //must be, because I want do restart this (new) task, not last task. return(true) static function DoGetMark(AB) local Get:=AB:GetList[AB:Tb:ColPos] Get:Row:=AB:Row+AB:Freeze-AB:FormTop+AB:Tb:ColPos+1 Get:Col:=AB:Col+Get:Cargo[nColOffset] EditGet(Get,false) if LastKey()==K_ENTER; Get:VarPut("x"); endif return(true) static function DoneFilter(View,AB,i,lAppend,cName,cExpr,lMark,Info) //Save values into: View:Filter & cIFR local x local OldS:=Select() cName:=" "+AllTrim(cName)+" " cExpr:=AllTrim(cExpr) begin break select (View:Alias) x:=&(cExpr) recover break select (OldS) if Empty(SetLastTask()); AB:Top(false); endif if AB:ID<>SetLastTask():ID; AB:Top(false); endif if Alert(ResTxt(096)+";"+ResTxt(058)+" "+Lower(ResTxt(062)),ResTxt(124))==1 AB:Paint(false) IEval(4,{|j|ATrueDel(View:Filter[j],i)}) if !Info:IsDead; Info:Done(); endif GetActiveMenu():EnableItem(View:MenuFltID) return(true) else return(false) endif end break View:Filter[1,i]:=cName View:Filter[2,i]:=cExpr View:Filter[4,i]:=lMark repeat if (x:=LogSet())==1 //save the filter on disk select (cIFR) if lAppend net append blank continue else FindIfrItem(View,i,"F",true) net rlock continue endif if NetErr(); select (OldS); return(false); endif field->ViewID:=View:ViewID field->Code:="F" field->Data:=cName+v_data_sep+cExpr+v_data_sep+Transform(lMark,) commit net unlock endif until x==1 or Alert(ResTxt(072)+";"+ResTxt(074),ResTxt(125))<>1 if !Info:IsDead; Info:Done(); endif GetActiveMenu():EnableItem(View:MenuFltID) select (OldS) return(true) //***************************************************************************** // View:ModReport(ID,WinName,R,C,CurSize,Clr,Shadow) --> nil // virtual modify Report process // method function ViewModReport(ID,WinName,R,C,CurSize,Clr,Shadow) local Ch local ar:=::Report[1] local arl:=::Report[3] local object Mnu of Mnu if LogSet()<>1 if Alert(ResTxt(072)+";"+ResTxt(075)+" "+Lower(ResTxt(055))+" "+ResTxt(076),ResTxt(123))<>1 return(false) endif endif default R to Row() default C to Col() ::MenuRptID:=ID //used in EditReport! (thread task must temporary disable own menu_item!) Mnu:InsBlock:={|Mnu|InsReport(self,WinName,Clr,Shadow)} Mnu:DelBlock:={|Mnu|DelReport(self,Mnu,R,C,CurSize,ar,arl)} Mnu:CanAppend:=true if Empty(ar) if InsReport(self,WinName,Clr,Shadow) PauseKey(0) //remove nSwapTask from keyboard queue else SetLastKey(0) return(true) endif else Mnu:Init("",R,C,CurSize,ar,arl) if AScan(arl,true)==0; StuffKey(K_INS); endif //for empty menu do append if Mnu:Process()>0; EditReport(self,Mnu:Choice,false,WinName,Clr,Shadow); endif Mnu:Done() endif do case case LastKey()==nSwapTask; SetLastKey(K_ENTER) case LastKey()==K_ESC and SetQuickEsc(); StuffKey(K_ESC) endcase return(true) static function InsReport(View,WinName,Clr,Shadow) local i,cName,cFile if Alert(ResTxt(104),ResTxt(123))<>1; return(false); endif i:=Len(View:Report[1])+1 cName:="~"+NTrim(i)+"." AAdd(View:Report[1],cName) AAdd(View:Report[2],{"",{},"",false}) //in future := {cTop,aFields,cBottom,lOnlyTotals} AAdd(View:Report[3],true) EditReport(View,i,true,WinName,Clr,Shadow) //append into cIFR & View:Report SetMenuCmd(0) //force restart task (in menu) StuffKeys(Chr(nSwapTask)+Chr(K_END)) //exit from Mnu:Process() & restart task, go end of line. return(true) static function DelReport(View,Mnu,R,C,CurSize,ar,arl) local x local s:=Select() local i:=Mnu:Choice if AScan(Mnu:SelItems,true)==0; return(false); endif if Alert(ResTxt(105),ResTxt(123))<>1; return(false); endif repeat if (x:=LogSet())==1 //delete the report on disk select (cIFR) if FindIfrItem(View,i,"R",false) net delete continue endif select (s) endif until x==1 or Alert(ResTxt(072)+";"+ResTxt(074),ResTxt(125))<>1 IEval(3,{|j|ATrueDel(View:Report[j],i)}) Mnu:Choice:=Min(Mnu:Choice,Len(ar)) Mnu:Hide() Mnu:Init("",R,C,CurSize,ar,arl) return(true) static function EditReport(View,i,lAppend,WinName,Clr,Shadow) //create new task, done menu, go into new task! local cName:=PadR(LTrim(View:Report[1,i]),nLenIFRName) local cTop:=PadR(LTrim(View:Report[2,i,1]),n_foot_max) local aFields:=View:Report[2,i,2] local cBottom:=PadR(LTrim(View:Report[2,i,3]),n_foot_max) local lOnlyTotals:=View:Report[2,i,4] local object AB of ABrowse //new task local ABName:=if(lAppend,ResTxt(060),ResTxt(041))+" "+Lower(ResTxt(044)) AB:CanSwap:=false AB:FormActive:=true AB:CanAppend:=false AB:MoreRecords:=false AB:Init(StrTran(ABName,"~")+": "+WinName,,,,,Clr,Shadow) AB:AddBlock(,ResTxt(056),"SYS:->RPT_NAME", {|x|if(nil==x,cName,cName:=x)}) AB:AddBlock(,ResTxt(047),"SYS:->RPT_TOP", {|x|if(nil==x,cTop,cTop:=x)},,"@S"+NTrim(nLenTopBottom)) AB:AddBlock(,ResTxt(048),"SYS:->RPT_FIELDS",{||ResTxt(133)},,,,{||if(LastKey()==K_ENTER,FieldProcess(View,i,Clr,Shadow),true)}) AB:AddBlock(,ResTxt(049),"SYS:->RPT_BOTTOM",{|x|if(nil==x,cBottom,cBottom:=x)},,"@S"+NTrim(nLenTopBottom)) AB:AddBlock(,ResTxt(193),"SYS:->RPT_ONLY", {|x|if(!Empty(x),lOnlyTotals:=!lOnlyTotals,)," "+ResTxt(123)[if(lOnlyTotals,1,2)]+" "},{|AB|DoGetMark(AB)}) AB:PostInit() AB:DoneBlock:={|o|DoneReport(View,o,i,lAppend,cName,cTop,cBottom,lOnlyTotals)} GetActiveMenu():DisableItem(View:MenuRptID) //new task !!! SetLastTask(nil) //must be, because I want do restart this new task, not last task. return(true) static function FieldProcess(View,ii,Clr,Shadow) local i,ee,p,p1,p2,p3,p4,p5,p6 local cYes:=ResTxt(123)[1] local cNo:=Space(Len(cYes)) local MaxC:=0 local MnuItems:={} local object UpAb of UpABrowse local OldShow:=SetDialog(true) local OldHelp:=SetHelpIdx(true) local aFields:=View:Report[2,ii,2] SetCursor(SC_NONE) SaveDOut(ResTxt(162)) AEval(View:Fields,{|e|MaxC:=Max(MaxC,Len(e[2]))}) AEval(View:Fields,{|e|AAdd(MnuItems," "+PadR(e[2],MaxC+1))}) // //always add recNo() ee:=if(Empty(aFields),false,(aFields[1,1]==ResTxt(051))) AAdd(UpAb:Arr,{ee, PadR(ResTxt(051),MaxC), if(ee,aFields[1,2],PadR(ResTxt(051),nLenColTitle)), false, 0}) // //Get all fields from View:Fields, set "˚" for field from aFields //UpAb:Arr:={{lSelected,cShortName,cTitle,lTotal,nIndexSubTotal},...} //View:Report[2,i,2]:=aFields:={{cShortName,cTitle,cField,cPicture,lTotal,cSubTotal},...} //View:Fields:={{cLongName,cShortName,cAlias,cField,cPicture,bWhen,bValid},...} for i:=1 to Len(View:Fields) ee:=View:Fields[i] p1:=(p:=AScan(aFields,{|x|x[3]==if(ValType(ee[4])=="B",ee[3],ee[3]+"->"+ee[4])},,i+1))>0 p2:=PadR(ee[2],MaxC) p3:=PadR(if(p1,aFields[p,2],p2),nLenColTitle) p4:=p1 and !Empty(aFields[p,5]) p5:=if(p1 and !Empty(aFields[p,6]),; AScan(View:Fields,{|x|aFields[p,6]==if(ValType(x[4])=="B",x[3],x[3]+"->"+x[4])}),; 0; ) AAdd(UpAb:Arr,{p1,p2,p3,p4,p5}) endfor UpAb:GoodInit(ResTxt(082),-3,-3,Min(Len(UpAb:Arr)+2,MaxRow()-5),Min(4+Max(Len(ResTxt(083)),MaxC)+3+Max(Len(ResTxt(194)),nLenColTitle)+3+Max(Len(ResTxt(084)),Len(cYes))+3+Max(Len(ResTxt(085)),MaxC)+1,MaxCol()-6)) UpAb:AddBlock(,Chr(240),,{||if(UpAb:Arr[UpAb:N,1],"˚","x")} ) UpAb:AddBlock(,ResTxt(083),"SYS:->RPT_IN_SEL", {||UpAb:Arr[UpAb:N,2]}, {||DoGetField(UpAb,View)} ) UpAb:AddBlock(,ResTxt(194),"SYS:->RPT_IN_TITLE",{|x|if(nil==x,UpAb:Arr[UpAb:N,3],UpAb:Arr[UpAb:N,3]:=x)}, {||DoGetTitle(UpAb,View)} ) UpAb:AddBlock(,ResTxt(084),"SYS:->RPT_IN_TOT", {||if(UpAb:Arr[UpAb:N,4],cYes,cNo)}, {||DoGetTotal(UpAb,View)} ) UpAb:AddBlock(,ResTxt(085),"SYS:->RPT_IN_SUBT", {||if(UpAb:Arr[UpAb:N,5]>0,UpAb:Arr[UpAb:Arr[UpAb:N,5],2],Space(MaxC))}, {||DoGetSubTotal(UpAb,View,MnuItems,Clr,Shadow)} ) for p:=1 to 5 (UpAb:Tb:GetColumn(p)):ColorBlock:={||if(UpAb:Arr[UpAb:N,1],{nNormal,nUnSelect},{nExtension,nUnSelect})} endfor UpAb:CanMoveCursor:=false UpAb:CanAppend:=false UpAb:CanSwap:=false UpAb:Freeze:=1 UpAb:Paint() DOut(ResTxt(154)); SetDialog(false) SaveHelpIdx({14}); SetHelpIdx(false) UpAb:Process() //--------------------------------------------- SetHelpIdx(true); RestHelpIdx(); SetHelpIdx(OldHelp) SetDialog(true); RestDOut(); SetDialog(OldShow) View:Report[2,ii,2]:={} // //work around RecNo() if UpAb:Arr[1,1]; AAdd(View:Report[2,ii,2],{ResTxt(051),UpAb:Arr[1,3],"RecNo()",,,}); endif // //build View:Report[2,ii,2] //UpAb:Arr:={{lSelected,cShortName,cTitle,lTotal,nIndexSubTotal},...} (paralel array for View:Fields) //View:Report[2,ii,2]:=aFields:={{cShortName,cTitle,cField,cPicture,lTotal,cSubTotal},...} //View:Fields:={{cLongName,cShortName,cAlias,cField,cPicture,bWhen,bValid},...} for i:=2 to Len(UpAb:Arr) ee:=UpAb:Arr[i] if ee[1] p1:=View:Fields[i-1,2] p2:=AllTrim(ee[3]) p3:=View:Fields[i-1,3]+"->"+View:Fields[i-1,4] p4:=if(!Empty(View:Fields[i-1,5]), View:Fields[i-1,5], nil) p5:=if(ee[4], true, nil) p6:=if(ee[5]>1, View:Fields[ee[5]-1,3]+"->"+View:Fields[ee[5]-1,4], nil) AAdd(View:Report[2,ii,2],{p1,p2,p3,p4,p5,p6}) endif endfor UpAb:Done() RestDOut() SetLastKey(0) StuffKey(K_DOWN) return(true) //into validation of EditReport static function DoGetField(UpAb,View) returnif UpAb:N>1 and ValType(View:Fields[UpAb:N-1,4])=="B" with false UpAb:Arr[UpAb:N,1]:=!UpAb:Arr[UpAb:N,1] if !UpAb:Arr[UpAb:N,1] UpAb:Arr[UpAb:N,4]:=false UpAb:Arr[UpAb:N,5]:=0 endif UpAb:Tb:RefreshCurrent() PauseKey() StuffKey(K_DOWN) return(true) static function DoGetTitle(UpAb,View) returnif UpAb:N>1 and ValType(View:Fields[UpAb:N-1,4])=="B" with false UpAb:Arr[UpAb:N,1]:=true UpAb:DoGet() UpAb:Tb:RefreshCurrent() StuffKey(K_DOWN) return(true) static function DoGetTotal(UpAb,View) returnif UpAb:N>1 and ValType(View:Fields[UpAb:N-1,4])=="B" with false if UpAb:N>1 UpAb:Arr[UpAb:N,4]:=!UpAb:Arr[UpAb:N,4] if ValType(&(View:Fields[UpAb:N-1,3]+"->"+View:Fields[UpAb:N-1,4]))<>"N" Alert(ResTxt(077)) UpAb:Arr[UpAb:N,4]:=false endif if UpAb:Arr[UpAb:N,4] UpAb:Arr[UpAb:N,1]:=true else UpAb:Arr[UpAb:N,5]:=0 endif UpAb:Tb:RefreshCurrent() endif PauseKey() StuffKey(K_DOWN) return(true) static function DoGetSubTotal(UpAb,View,MnuItems,Clr,Shadow) local lExit,Choice returnif UpAb:N>1 and ValType(View:Fields[UpAb:N-1,4])=="B" with false if UpAb:N>1 lExit:=false object Choice of Choice if UpAb:Arr[UpAb:N,5]>0 UpAb:Arr[UpAb:N,5]:=0 else if ValType(&(View:Fields[UpAb:N-1,3]+"->"+View:Fields[UpAb:N-1,4]))<>"N" Alert(ResTxt(077)) UpAb:Arr[UpAb:N,4]:=false else Choice:FastInit(,Row(),Col(),UpAb:Tb:ColWidth(4),MnuItems,Clr,Shadow) UpAb:Arr[UpAb:N,5]:=Choice:Process() Choice:Done() if UpAb:Arr[UpAb:N,5]>0 UpAb:Arr[UpAb:N,1]:=true UpAb:Arr[UpAb:N,4]:=true UpAb:Arr[UpAb:N,5]++ endif endif endif UpAb:Tb:RefreshCurrent() endif PauseKey() StuffKey(K_DOWN) return(true) static function DoneReport(View,AB,i,lAppend,cName,cTop,cBottom,lOnlyTotals) //Save values into: View:Report & cIFR local x local cExpr:="" local OldS:=Select() local aFields:=View:Report[2,i,2] if Empty(aFields) select (OldS) if Empty(SetLastTask()); AB:Top(false); endif if AB:ID<>SetLastTask():ID; AB:Top(false); endif if Alert(ResTxt(095),ResTxt(124))==1 AB:Paint(false) IEval(3,{|j|ATrueDel(View:Report[j],i)}) GetActiveMenu():EnableItem(View:MenuRptID) return(true) else return(false) endif endif AEval(aFields,{|e|cExpr+=";"+e[1]+","+; e[2]+","+; e[3]+","+; if(nil==e[4],"",e[4])+","+; if(nil==e[5],"F",Transform(e[5],))+","+; if(nil==e[6],"",e[6]); }; //cShortName,cTitle,cField,cPicture,lTotal,cSubTotal ) cName:=" "+AllTrim(cName)+" " cTop:=AllTrim(cTop) cBottom:=AllTrim(cBottom) View:Report[1,i]:=cName View:Report[2,i,1]:=cTop View:Report[2,i,3]:=cBottom View:Report[2,i,4]:=lOnlyTotals View:Report[3,i]:=true repeat if (x:=LogSet())==1 //save the filter on disk select (cIFR) if lAppend net append blank continue else FindIfrItem(View,i,"R",true) net rlock continue endif if NetErr(); select (OldS); return(false); endif field->ViewID:=View:ViewID field->Code:="R" field->Data:=cName+v_data_sep+cTop+v_data_sep+SubStr(cExpr,2)+v_data_sep+cBottom+v_data_sep+Transform(lOnlyTotals,) commit net unlock endif until x==1 or Alert(ResTxt(072)+";"+ResTxt(074),ResTxt(125))<>1 GetActiveMenu():EnableItem(View:MenuRptID) select (OldS) return(true) //***************************************************************************** // View:VProcess() --> true // thread virtual view or edit process // called how Task:VProcess() // method function ViewVProcess() local cMsg:="" local OldKey:=SetKey(K_ALT_F10,{||SlipMenu(self)}) AEval(::Action,{|e|e[3]:=SetKey(e[1],e[2]),if(!Empty(e[4]) and ValType(e[4])=="C",cMsg+=","+e[4],nil)}) cMsg:=StrTran(cMsg,",,",",") ::AddMsg:=SubStr(cMsg,2) ::super(DBrowse):VProcess() AEval(::Action,{|e|SetKey(e[1],e[3])}) SetKey(K_ALT_F10,OldKey) return(true) //----------------------------------------------------------------------------- // View::SlipMenu() --> true/false // slip menu for thread virtual view or edit process // static function SlipMenu(View) local Action,Menu,MD if Empty(View:MenuID); return(false); endif Menu:=GetActiveMenu() MD:=Menu:GetParentMD(View:MenuID) SetCursor(SC_NONE) SetPos(View:Row,View:Col+2) SaveDOut(ResTxt(140)+if(!Empty(View:AddMsg),","+View:AddMsg,"")) SaveHelpIdx({}) //disable menu if (Action:=Menu:ItemEntry(MD,-1))>0 and !Empty(Menu:Block[Action]) Menu:NewTask:=Action StuffKey(nSwapTask) else if Action>0 SetMenuCmd(0) StuffKey(nSwapTask) else if SetQuickEsc(); InKeyWait(); endif //remove Esc from queue endif endif RestHelpIdx() RestDOut() return(true) //***************************************************************************** // View:Done(lRePaint) --> true/false // destroy this object. // method function ViewDone(lRePaint) local lExit:=::super(DBrowse):Done(lRePaint) if lExit ATrueDel(VList,AScan(VList,{|e|e:ID==::ID})) //this is Window:ID (unique for each window, i.e: unique for each live view object) endif return(lExit) //------------------------------------------------------- eof (c)JHK ----------